package com.sky.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Map;
/**
 * 1. 当前包名: com.sky.utils    存放工具类相关的类
 * 2. 当前类名: JwtUtil    JWT 工具类
 */

/**
 * JwtUtil; 用于生成和解析 JWT（JSON Web Token）令牌。
 * 该类封装了 JWT 令牌的创建和解析过程，使用 HMAC SHA256 算法进行签名。
 * JWT 广泛用于 Web 应用的身份认证，通常用于用户身份验证的场景。
 */
public class JwtUtil {
    /**
     * * 知识点:
     * 1. **JWT（JSON Web Token）**：一种开放标准，用于在网络应用环境间以 JSON 格式传递声明。JWT 被广泛应用于身份验证和信息交换，通常由三部分组成：头部（Header）、有效载荷（Payload）、签名（Signature）。
     * 2. **HS256 签名算法**：HMAC SHA256 是一种基于密钥的加密哈希算法，常用于 JWT 签名。该算法保证了令牌的完整性和不可伪造性。
     * 3. **`JwtBuilder`**：用于构建 JWT 令牌对象。它支持设置 JWT 的各个部分，如有效载荷、过期时间、签名等。
     * 4. **`Claims`**：JWT 的有效载荷部分，其中包含声明信息，如用户身份信息等。
     * 5. **`SignatureAlgorithm.HS256`**：指定使用 HMAC SHA256 算法来进行 JWT 令牌的签名。此签名是通过 `secretKey` 密钥加密生成的。
     * 6. **`System.currentTimeMillis()`**：返回当前的毫秒时间戳，通常用于设置 JWT 的过期时间。
     * 7. **`StandardCharsets.UTF_8`**：指定字符编码为 UTF-8，用于将密钥转换为字节数组。
     */


    /**
     * 生成jwt
     * 使用Hs256算法, 私匙使用固定秘钥
     *
     * @param secretKey jwt秘钥
     * @param ttlMillis jwt过期时间(毫秒)
     * @param claims    设置的信息
     * @return
     */
    public static String createJWT(String secretKey, long ttlMillis, Map<String, Object> claims) {
        // 指定签名的时候使用的签名算法，也就是header那部分
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

        // 生成JWT的时间
        long expMillis = System.currentTimeMillis() + ttlMillis;
        Date exp = new Date(expMillis);

        // 设置jwt的body
        JwtBuilder builder = Jwts.builder()
                // 如果有私有声明，一定要先设置这个自己创建的私有的声明，这个是给builder的claim赋值，一旦写在标准的声明赋值之后，就是覆盖了那些标准的声明的
                .setClaims(claims)
                // 设置签名使用的签名算法和签名使用的秘钥
                .signWith(signatureAlgorithm, secretKey.getBytes(StandardCharsets.UTF_8))
                // 设置过期时间
                .setExpiration(exp);

        return builder.compact();
    }

    /**
     * Token解密
     *
     * @param secretKey jwt秘钥 此秘钥一定要保留好在服务端, 不能暴露出去, 否则sign就可以被伪造, 如果对接多个客户端建议改造成多个
     * @param token     加密后的token
     * @return
     */
    public static Claims parseJWT(String secretKey, String token) {
        // 得到DefaultJwtParser
        Claims claims = Jwts.parser()
                // 设置签名的秘钥
                .setSigningKey(secretKey.getBytes(StandardCharsets.UTF_8))
                // 设置需要解析的jwt
                .parseClaimsJws(token).getBody();
        return claims;
    }

}
/**
 * JwtUtilWithCustomClaims; 继承自 JwtUtil，允许用户在生成 JWT 时添加更多的自定义声明信息。
 * 该类用于扩展生成 JWT 的功能，提供更多灵活的选项。
 * public class JwtUtilWithCustomClaims {
 *   public static String createJWTWithCustomClaims(String secretKey, long ttlMillis, Map<String, Object> claims, Map<String, Object> additionalClaims) {
 *         // 指定签名算法
 *         SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
 *
 *         // 生成过期时间
 *         long expMillis = System.currentTimeMillis() + ttlMillis;
 *         Date exp = new Date(expMillis);
 *
 *         // 创建 JWT，并设置声明
 *         JwtBuilder builder = Jwts.builder()
 *                 .setClaims(claims)  // 设置用户传入的基本声明
 *                 .setClaims(additionalClaims)  // 添加额外的自定义声明
 *                 .signWith(signatureAlgorithm, secretKey.getBytes(StandardCharsets.UTF_8))  // 设置签名密钥
 *                 .setExpiration(exp);  // 设置过期时间
 *
 *         return builder.compact();  // 生成 JWT 字符串
 *     }
 *  }
 */
